package com.csy.user.entity.system.service.impl;

import com.csy.commons.constant.UserConstants;

import com.csy.commons.core.exception.CustomException;
import com.csy.commons.dto.SysDept;
import com.csy.user.entity.system.mapper.SysDeptMapper;
import com.csy.user.entity.system.service.SysDeptService;

import com.csy.user.utils.TreeSelect;

import io.seata.spring.annotation.GlobalTransactional;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Auther: sunxx
 * @Date: 2024/1/4 - 01 - 04 - 16:30
 * @Description: com.sxx.ajcommunity.system.service.impl
 * @version: 1.0
 */
@Service
public class SysDeptServiceImpl implements SysDeptService {


    @Resource
    private SysDeptMapper deptMapper;

    /**
     * 查询部门管理数据
     * @param dept
     * @return: java.util.List<com.msb.hjycommunity.system.domain.SysDept>
     */
    @Override
    public List<SysDept> selectDeptList(SysDept dept) {
        return deptMapper.selectDeptList(dept);
    }

    /**
     * 根据部门Id查询信息
     * @param deptId
     * @return: com.msb.hjycommunity.system.domain.SysDept
     */
    @Override
    public SysDept selectDeptById(Long deptId) {
        return deptMapper.selectDeptById(deptId);
    }


    /**
     * 新增部门信息
     * @param dept
     * @return: int
     */
    @Override
    @GlobalTransactional
    public int insertDept(SysDept dept) {
        //1. 获取当前节点的父节点
        SysDept parent = deptMapper.selectDeptById(dept.getParentId());

        //2. 父节点不是正常状态,则不允许新增子节点
        if(!UserConstants.DEPT_NORMAL.equals(dept.getStatus())){
            throw new CustomException(500,"部门停用,不允许新增");
        }

        //3. 设置 ancestors 祖级列表字段,记录的是当前节点的所有父节点id
        dept.setAncestors(parent.getAncestors() + "," + dept.getParentId());

        return deptMapper.insertDept(dept);
    }

    /**
     * 修改部门信息
     * @param dept
     * @return: int
     */
    @Override
    @GlobalTransactional
    public int updateDept(SysDept dept) {
        //获取父节点
        SysDept newParent = deptMapper.selectDeptById(dept.getParentId());

        //获取旧节点数据
        SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId());

        if(!Objects.isNull(newParent) && !Objects.isNull(oldDept)){
            //设置最新的祖级列表
            String newAncestors = newParent.getAncestors() + "," + newParent.getDeptId();
            dept.setAncestors(newAncestors);

            //修改子元素关系
            String oldAncestors = oldDept.getAncestors();
            updateDeptChildren(dept.getDeptId(),newAncestors,oldAncestors);
        }

        return deptMapper.updateDept(dept);
    }

    /**
     * 修改子元素关系
     * @param deptId        被修改的部门ID
     * @param newAncestors  新的父id集合
     * @param oldAncestors  旧的父id集合
     */
    private void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
        List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
        for (SysDept child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors,newAncestors));
        }
        if(children.size() > 0){
            deptMapper.updateDeptChildren(children);
        }
    }

    /**
     * 删除部门管理信息
     * @param deptId
     * @return: int
     */
    @Override
    @GlobalTransactional
    public int deleteDeptById(Long deptId) {
        return deptMapper.deleteDeptById(deptId);
    }


    /**
     * 校验部门名称是否唯一
     * @param dept
     * @return: java.lang.String
     */
    @Override
    public String checkDeptNameUnique(SysDept dept) {

        SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
        if(!Objects.isNull(info)){
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 是否存在子节点
     */
    @Override
    public boolean hasChildByDeptId(Long deptId) {
        int result = deptMapper.hasChildByDeptId(deptId);
        return result > 0 ? true : false;
    }


    /**
     * 查询部门是否存在用户
     * @param deptId
     * @return: boolean
     */
    @Override
    public boolean checkDeptExistUser(Long deptId) {
        int result = deptMapper.checkDeptExistUser(deptId);
        return result > 0 ? true : false;
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param deptList 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> deptList) {
        List<SysDept> deptTrees = buildDeptTree(deptList);
        List<TreeSelect> selectList = deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());

        return selectList;
    }

    /**
     * 构建部门树结构
     * @param deptList
     * @return:
     */
    private List<SysDept> buildDeptTree(List<SysDept> deptList) {
        //要返回的list
        List<SysDept> returnList = new ArrayList<>();

        //获取所有部门的deptId,保存到List
        List<Long> deptIdList = new ArrayList<>();
        for (SysDept sysDept : deptList) {
            deptIdList.add(sysDept.getDeptId());
        }

        deptList.stream()
                //如果是顶级节点,遍历该节点下的所有子节点
                .filter(dept -> !deptIdList.contains(dept.getParentId()))
                .forEach(dept -> {
                    //递归获取子节点
                    recursionFn(deptList,dept);
                    returnList.add(dept);
                });

        return returnList;
    }

    /**
     * 递归操作
     * @param deptList 部门集合
     * @param dept 父部门
     */
    private void recursionFn(List<SysDept> deptList, SysDept dept) {
        //得到子节点
        List<SysDept> childList = getChildList(deptList,dept);
        dept.setChildren(childList);
        for (SysDept child : childList) {
            //判断是否还有子节点
            if(hasChild(deptList,child)){
                //递归调用
                recursionFn(deptList,child);
            }
        }
    }

    /**
     * 得到子节点列表
     * @param deptList
     * @param dept
     * @return:
     */
    private List<SysDept> getChildList(List<SysDept> deptList, SysDept dept) {
        List<SysDept> subList = new ArrayList<SysDept>();

        subList = deptList.stream()
                .filter(subDept -> !Objects.isNull(subDept.getParentId())
                        && subDept.getParentId().longValue() == dept.getDeptId().longValue())
                .collect(Collectors.toList());

        return subList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDept> list,SysDept dept){
        return getChildList(list,dept).size() > 0 ? true : false;
    }
}